package Java7_Concurrency_Cookbook.fork_join.recursive_task_fork_join;

import java.util.List;
import java.util.concurrent.ForkJoinPool;

/**
 * 把pool.execute(task)直接执行的线程成为工作者线程<br/>
 * 此示例中, 工作者线程寻找.log结尾的文件时,如果发现文件时一个文件夹,
 * 它将会创建另一个Task对象来处理这个文件夹<br/>
 * 并调用fork()方法把这个新的Task对象发送到线程池中. fork()方法会立即返回.<br/>
 * 因此工作者线程可以继续处理文件夹里的其他内容而不会阻塞, 这就是异步执行任务!<br/>
 * <br/>
 * 一旦工作者线程处理完指定文件夹里的所有内容, 它将调用join()方法等待发送到线程池中的所有子任务执行完成.<br/>
 * join()方法在主任务中被调用, 然后等待任务执行结束, 并通过compute()方法返回值.<br/>
 * <br/>
 * 通常, fork()和join()成对出现<br/>
 * fork()用于将任务发送到线程池, 发送成功后立即返回.
 * join()用于获取fork()发送的线程的执行结果.<br/>
 * 通常, 为了方便join()获取fork()发送的线程的执行结果,
 * fork()发送的任务会存在一个列表中,方便join()通过列表访问任务的执行结果.<br/>
 * 如示例FolderProcessor line 32-33中展示的那样:
 * <pre>
 *     task.fork();
 *     tasks.add(task);
 * </pre>
 * @author lixiangke
 * @date 2017/11/22
 */
public class Main {
    public static void main(String[] args) throws InterruptedException {
        ForkJoinPool pool = new ForkJoinPool();
        FolderProcessor system = new FolderProcessor("C\\windows", "log");
        FolderProcessor apps = new FolderProcessor("C\\Program Files", "log");
        FolderProcessor documents = new FolderProcessor("C:\\Users\\lixiangke\\Documents", "log");
        pool.execute(system);
        pool.execute(apps);
        pool.execute(documents);

//        do {
//            System.out.printf("**********************\n");
//            System.out.printf("Main: Parallelism: %d\n", pool.getParallelism());
//            System.out.printf("Main: Active Threads: %d\n", pool.getActiveThreadCount());
//            System.out.printf("Main: Zoom Count: %d\n", pool.getQueuedTaskCount());
//            System.out.printf("Main: Steal Count    : %d\n", pool.getStealCount());
//            System.out.printf("**********************\n");
//            TimeUnit.MINUTES.sleep(1);
//        } while ((!system.isDone()) || (!apps.isDone()) || (!documents.isDone()));

        pool.shutdown();

        List<String> results = system.join();
        System.out.printf("System: %d files found.\n", results.size());
        results = apps.join();
        System.out.printf("Apps: %d files found.\n", results.size());
        results = documents.join();
        System.out.printf("Documents: %d files found.\n", results.size());
    }
}
